package com.web.kdl.component;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.web.kdl.controller.send.Send;
import com.web.kdl.dao.flywheelDataAnalysis.FlywheelDataAnalysisDao;
import com.web.kdl.daoV2.matrix.MatrixDao;
import com.web.kdl.daoV2.site.SiteDao;
import com.web.kdl.entity.flywheelDataAnalysis.FlywheelDataAnalysis;
import com.web.kdl.entity.matrix.Matrix;
import com.web.kdl.entity.site.Site;
import com.web.kdl.service.createTable.TableDataType;
import com.web.kdl.util.TableNameUtils;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.internal.util.stereotypes.Lazy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Component
@Slf4j
public class MyScheduledTask {

    @Autowired
    @Lazy
    private Send send;
    @Autowired
    private MatrixDao matrixDao;
    @Autowired
    private SiteDao siteDao;
    @Autowired
    private FlywheelDataAnalysisDao flywheelDataAnalysisDao;
    @Autowired
    private PlatformTransactionManager transactionManager;


    // 每10秒执行一次，定时执行，至少15秒以上
//    @Scheduled(fixedRate = 30000)
//    public void fixedDelayTask() {
//        System.out.println("开始执行,当前时间:"+ Send.getCurrentTime());
//        send.execute();
//        System.out.println("执行结束");
//    }


    @Scheduled(cron = "0 0 * * * ?")
    public void executeAtMidnight() {
        log.info("开始数据同步：{}", LocalDateTime.now());

        List<Site> sites = siteDao.selectList(null);
        ExecutorService executor = Executors.newFixedThreadPool(5);

        for (Site site : sites) {
            List<Matrix> matrices = matrixDao.selectList(
                    new LambdaQueryWrapper<Matrix>().eq(Matrix::getSiteId, site.getId())
            );

            List<String> tempTables = TableNameUtils.getAllDataTableName(matrices, site.getSumSite(), TableDataType.TEMP);
            List<String> dayTables = TableNameUtils.getAllDataTableName(matrices, site.getSumSite(), TableDataType.DAY);
            List<String> minuteTables = TableNameUtils.getAllDataTableName(matrices, site.getSumSite(), TableDataType.MINUTE);

            for (int i = 0; i < tempTables.size(); i++) {
                String tempTable = tempTables.get(i);
                String dayTable = dayTables.get(i);
                String minuteTable = minuteTables.get(i);

                executor.submit(() -> processData(tempTable, dayTable, minuteTable));
            }
        }

        executor.shutdown();
        try {
            if (!executor.awaitTermination(1, TimeUnit.HOURS)) {
                log.warn("数据同步线程未全部完成，超时退出");
            }
        } catch (InterruptedException e) {
            log.error("等待线程池终止异常", e);
            Thread.currentThread().interrupt();
        }
    }

    private void processData(String tempTable, String dayTable, String minuteTable) {
        List<FlywheelDataAnalysis> allDayData = flywheelDataAnalysisDao.getDayTempDataList(tempTable);
        if (allDayData.isEmpty()) {
            log.info("{} temp 表无数据，跳过", tempTable);
            return;
        }

        TransactionTemplate tx = new TransactionTemplate(transactionManager);
        boolean dayInsertSuccess = false;
        boolean allMinutesSuccess = true;

        //  插入天数据
        try {
            tx.execute(status -> {
                flywheelDataAnalysisDao.insertlistflywheel(allDayData, dayTable);
                return true; // 避免 IDE 警告
            });
            dayInsertSuccess = true;
            log.info("{} 插入天数据成功：{} 条", dayTable, allDayData.size());
        } catch (Exception e) {
            log.error("{} 插入天数据失败，保留 temp 表数据", dayTable, e);
        }

        //  生成并插入分钟数据
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        List<LocalDate> needMinuteDates = allDayData.stream()
                .map(d -> LocalDateTime.parse(d.getTime(), formatter).toLocalDate())
                .distinct()
                .sorted()
                .collect(Collectors.toList());

        for (LocalDate date : needMinuteDates) {
            LocalDateTime startOfDay = date.atStartOfDay();
            List<FlywheelDataAnalysis> minuteDataList = new ArrayList<>();

            for (int j = 0; j < 96; j++) {
                LocalDateTime pointStart = startOfDay.plusMinutes(j * 15);
                LocalDateTime pointEnd = pointStart.plusMinutes(15);

                List<FlywheelDataAnalysis> record = flywheelDataAnalysisDao.getNearestDataInInterval(tempTable, pointStart, pointEnd);
                if (!record.isEmpty()) minuteDataList.addAll(record);

                // 每 500 条批量插入
                if (minuteDataList.size() >= 500) {
                    boolean b = !insertMinuteBatch(minuteDataList, minuteTable, tx);
                    if (!b) allMinutesSuccess = false;
                    minuteDataList.clear();
                }
            }

            // 插入剩余不足 500 条
            if (!minuteDataList.isEmpty()) {
                if (insertMinuteBatch(minuteDataList, minuteTable, tx)) allMinutesSuccess = false;
            }

            log.info("{} 插入分钟数据（{}）完成", minuteTable, date);
        }

        //  清空 temp 表（仅当天数据和分钟数据都成功时）
        if (dayInsertSuccess && allMinutesSuccess) {
            try {
                deleteTempTableBeforeToday(tempTable, tx);
                log.info("清空 temp 表成功：{}", tempTable);
            } catch (Exception e) {
                log.error("清空 temp 表失败：{}", tempTable, e);
            }
        } else {
            log.warn("未清空 temp 表 {}，天数据或分钟数据插入未完全成功", tempTable);
        }
    }

    private boolean insertMinuteBatch(List<FlywheelDataAnalysis> dataList, String tableName, TransactionTemplate tx) {
        try {
            tx.execute(status -> {
                flywheelDataAnalysisDao.insertlistflywheel(new ArrayList<>(dataList), tableName);
                return true;
            });
            return false;
        } catch (Exception e) {
            log.error("{} 批量插入分钟数据失败，保留 temp 表数据", tableName, e);
            return true;
        }
    }

    private void deleteTempTableBeforeToday(String tempTable, TransactionTemplate tx) {
        int batchSize = 1000;
        while (true) {
            // 批量删除并确保返回值非 null
            Integer deleted = tx.execute(status -> {
                Integer result = flywheelDataAnalysisDao.deleteBeforeTodayBatch(tempTable, batchSize);
                return (result != null) ? result : 0;
            });

            // 小于 batchSize 表示已经删除完毕
            if (deleted == null || deleted < batchSize) break;
        }
    }




}
